﻿using Furion.DataEncryption;
using System.Reflection;
using System.Security.Claims;

namespace GoodAdmin.Web.Core;

public class JwtHandler : AppAuthorizeHandler
{
    /// <summary>
    /// 自动刷新Token
    /// </summary>
    /// <param name="context"></param>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public override async Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
    {
        var expire = App.GetOptions<JWTSettingsOptions>().ExpiredTime.ToInt();//获取过期时间(分钟)
        //var currentHttpContext = context.GetCurrentHttpContext();
        if (JWTEncryption.AutoRefreshToken(context, httpContext,
                expire, expire * 2))
        {
            //验证token是否有效
            if (CheckToken(httpContext, expire))
            {
                await AuthorizeHandleAsync(context);
            }
            else
            {
                httpContext.Response.StatusCode = 401;
                return;
            }  
        }
        else
        {
            httpContext.Response.StatusCode = 401;
            return;               
        }
    }
    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
    {
        // 这里写您的授权判断逻辑，授权通过返回 true，否则返回 false
        return CheckAuthorizationAsync(httpContext);
    }


    private static async Task<bool> CheckAuthorizationAsync(DefaultHttpContext httpContext)
    {
        //超级管理员都能访问
        if (UserManager.SuperAdmin) return true;
        var controller = httpContext.GetControllerActionDescriptor();
        //接口是否有【允许登录用户访问】特性
        var allowLoginUse = controller.MethodInfo.GetCustomAttribute<AllowLoginUserAttribute>();

        if (allowLoginUse != null)
        {
            return true;
        }
        
        var baseService = App.GetService<IBaseService>();
        //公共角色是否有该接口权限
        var commonApiRole = await baseService.GetCommonApiRoleByRequest();
        if(commonApiRole!=null)return true;

        //用户角色中是否有该接口权限
        var userApiRole = await baseService.GetUserApiRoleByRequest();
        return userApiRole != null;
        //// 路由/按钮名称
        //var routeName = httpContext.Request.Path.Value;
        ////获取用户接口权限
        //var apiRoles = await baseService.GetUserApiRoles();

        //if (apiRoles == null || apiRoles.Count == 0) return false;
        ////根据角色数据信息与访问路由匹配
        //return apiRoles.Any(u => u.RouteUrl == routeName);
    }
    /// <summary>
    /// 验证用户token是否有效
    /// </summary>
    private static bool CheckToken(DefaultHttpContext context,int expire)
    {
        //当前上下文token
        var token = JWTEncryption.GetJwtBearerToken(context);
        //当前用户id
        var userId = App.User?.FindFirstValue(ClaimConst.UserId);
        //获取缓存实例
        var cache = App.GetService<IRedisCacheManager>();
        var cacheKey = CacheConst.UserToken + userId;
        var tokenList = cache.Get<List<TokenInfo>>(cacheKey);
        if (tokenList == null) return false;

        var tokenInfo= tokenList.Where(it=>it.Token==token).FirstOrDefault();
        if (tokenInfo == null) return false;

        var accessToken= context.Response.Headers["access-token"].ToString();
        if (!string.IsNullOrEmpty(accessToken))//如果有新的刷新token
        {
            tokenList.Remove(tokenInfo);//移除之前旧的token信息
            tokenInfo.Token = accessToken;//新的token
            tokenInfo.TokenExpireTime = DateTime.Now.AddMinutes(expire);//新的过期时间
            tokenList.Add(tokenInfo);//添加信息的token信息
            cache.Set(cacheKey, tokenList);
        }
        return true;
    }
}
